package com.haohan.cloud.scm.opc.core.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.haohan.cloud.scm.api.aftersales.entity.ReturnOrder;
import com.haohan.cloud.scm.api.aftersales.req.ReturnOrderDetailReq;
import com.haohan.cloud.scm.api.aftersales.req.ReturnOrderReq;
import com.haohan.cloud.scm.api.constant.enums.aftersales.ReturnStatusEnum;
import com.haohan.cloud.scm.api.constant.enums.common.ReviewStatusEnum;
import com.haohan.cloud.scm.api.constant.enums.opc.YesNoEnum;
import com.haohan.cloud.scm.api.constant.enums.saleb.BillTypeEnum;
import com.haohan.cloud.scm.api.constant.enums.supply.PdsOfferStatusEnum;
import com.haohan.cloud.scm.api.constant.enums.supply.ShipStatusEnum;
import com.haohan.cloud.scm.api.opc.entity.SupplierPayment;
import com.haohan.cloud.scm.api.opc.req.payment.FetchSupplierPaymentReq;
import com.haohan.cloud.scm.api.opc.req.payment.PaymentDetailReq;
import com.haohan.cloud.scm.api.saleb.entity.Buyer;
import com.haohan.cloud.scm.api.saleb.req.BuyerReq;
import com.haohan.cloud.scm.api.supply.entity.OfferOrder;
import com.haohan.cloud.scm.api.supply.entity.Supplier;
import com.haohan.cloud.scm.api.supply.entity.SupplyOrder;
import com.haohan.cloud.scm.api.supply.req.OfferOrderReq;
import com.haohan.cloud.scm.api.supply.req.PaymentParam;
import com.haohan.cloud.scm.api.supply.req.SupplierReq;
import com.haohan.cloud.scm.api.supply.req.SupplyOrderReq;
import com.haohan.cloud.scm.api.supply.resp.FetchSupplierPaymentResp;
import com.haohan.cloud.scm.api.supply.resp.SupplierPaymentResp;
import com.haohan.cloud.scm.common.tools.exception.EmptyDataException;
import com.haohan.cloud.scm.common.tools.exception.ErrorDataException;
import com.haohan.cloud.scm.opc.core.ISupplierPaymentCoreService;
import com.haohan.cloud.scm.opc.service.SupplierPaymentService;
import com.haohan.cloud.scm.opc.utils.ScmOpcUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author xwx
 * @date 2019/7/17
 */
@Slf4j
@Service
@AllArgsConstructor
public class SupplierPaymentCoreServiceImpl implements ISupplierPaymentCoreService {

    private final SupplierPaymentService supplierPaymentService;
    private final ScmOpcUtils scmOpcUtils;


    /**
     * 查询应付账单详情
     * @param req
     * @return
     */
    @Override
    public FetchSupplierPaymentResp fetchSupplierPayment(FetchSupplierPaymentReq req) {
        FetchSupplierPaymentResp resp = new FetchSupplierPaymentResp();
        //查询供应商货款
        SupplierPayment supplierPayment = supplierPaymentService.getById(req.getId());
        if (null==supplierPayment){
            throw new EmptyDataException("供应商货款为空");
        }
        resp.setSupplierPaymentId(supplierPayment.getSupplierPaymentId());
        resp.setStatus(supplierPayment.getStatus());
        resp.setCreateDate(supplierPayment.getCreateDate());
        resp.setBillType(supplierPayment.getBillType());

        if (supplierPayment.getBillType()== BillTypeEnum.purchase){
            //采购应付
            resp.setOfferOrderId(supplierPayment.getPayableSn());
            //查询报价单
//            OfferOrder offerOrder = new OfferOrder();
//            offerOrder.setPmId(req.getPmId());
//            offerOrder.setOfferOrderId(supplierPayment.getPayableSn());
            OfferOrderReq offerOrderReq = new OfferOrderReq();
            offerOrderReq.setPmId(req.getPmId());
            offerOrderReq.setOfferOrderId(supplierPayment.getPayableSn());
            OfferOrder one = scmOpcUtils.queryOfferOrder(offerOrderReq);
            resp.setOfferType(one.getOfferType());
            List<PaymentParam> list = new ArrayList<>();
            PaymentParam paymentParam = new PaymentParam();
            paymentParam.setSupplierName(one.getSupplierName());
            paymentParam.setGoodsName(one.getGoodsName());
            paymentParam.setUnit(one.getUnit());
            paymentParam.setBuyNum(one.getBuyNum());
            paymentParam.setDealPrice(one.getDealPrice());
            resp.setList(list);
        }
        if (supplierPayment.getBillType()== BillTypeEnum.orderBack){
            //TODO  退款应付
        }
        return resp;
    }

    /**
     * 创建应付账单
     *  根据 应付来源订单编号:payableSn/账单类型:billType 去查对应订单获取金额
     * @param supplierPayment 必需:pmId/payableSn/billType
     * @return
     */
    @Override
    public SupplierPayment createPayable(SupplierPayment supplierPayment) {
        SupplierPayment result;
        String pmId = supplierPayment.getPmId();
        String payableSn = supplierPayment.getPayableSn();
        // 是否已创建
        QueryWrapper<SupplierPayment> query = new QueryWrapper<>();
        query.lambda()
                .eq(SupplierPayment::getPmId, pmId)
                .eq(SupplierPayment::getPayableSn, payableSn);
        result = supplierPaymentService.getOne(query);
        if(null != result){
            return result;
        }
        switch (supplierPayment.getBillType()) {
            case purchase:
                // 采购应付 已中标
                result = initPayableByOfferOrder(pmId, payableSn);
                break;
            case orderBack:
                // 客户退款应付
                result = initPayableByReturnOrder(pmId, payableSn);
                break;
            default:
                result = null;
        }
        // 创建
        if(null != result){
            supplierPaymentService.save(result);
        }
        return result;
    }

    /**
     * 根据 退货单returnOrder 初始创建 应付账单
     * @param pmId
     * @param payableSn
     * @return
     */
    private SupplierPayment initPayableByReturnOrder(String pmId, String payableSn) {
        // 客户退货应付
        ReturnOrderReq req = new ReturnOrderReq();
        req.setPmId(pmId);
        req.setReturnSn(payableSn);
        ReturnOrder returnOrder = scmOpcUtils.fetchRefund(req);
        if(null == returnOrder){
            return null;
        }
        BuyerReq buyerReq = new BuyerReq();
        buyerReq.setId(returnOrder.getReturnCustomerId());
        buyerReq.setPmId(pmId);
        Buyer buyer = scmOpcUtils.queryBuyer(buyerReq);
        if(null == buyer){
            return null;
        }
        // 账单初始设置
        SupplierPayment result = new SupplierPayment();
        result.setPmId(pmId);
        result.setPayableSn(payableSn);
        result.setBillType(BillTypeEnum.orderBack);
        result.setSupplierPayment(returnOrder.getTotalAmount());
        result.setStatus(YesNoEnum.no);
        result.setSupplierId(returnOrder.getReturnCustomerId());
        // 订单成交日期 =>  退货单申请日期
        LocalDateTime applyTime = returnOrder.getApplyTime();
        if(null == applyTime){
            applyTime = returnOrder.getCreateDate();
        }
        result.setSupplyDate(applyTime.toLocalDate());
        result.setReviewStatus(ReviewStatusEnum.wait);
        result.setCustomerName(buyer.getBuyerName());
        result.setMerchantId(buyer.getMerchantId());
        result.setMerchantName(buyer.getMerchantName());
        return result;
    }

    /**
     * 根据 供应订单OfferOrder 初始创建 应付账单
     * @param pmId
     * @param payableSn
     * @return
     */
    private SupplierPayment initPayableByOfferOrder(String pmId, String payableSn) {
        // 供应订单
        SupplyOrderReq req = new SupplyOrderReq();
        req.setSupplySn(payableSn);
        SupplyOrder supplyOrder = scmOpcUtils.querySupplyOrder(req);
        if(null == supplyOrder){
            return null;
        }
        SupplierReq supplierReq = new SupplierReq();
        supplierReq.setId(supplyOrder.getSupplierId());
        supplierReq.setPmId(pmId);
        Supplier supplier = scmOpcUtils.querySupplier(supplierReq);
        if(null == supplier){
            return null;
        }
        // 账单初始设置
        SupplierPayment result = new SupplierPayment();
        result.setPmId(pmId);
        result.setPayableSn(payableSn);
        result.setBillType(BillTypeEnum.purchase);
        result.setSupplierPayment(supplyOrder.getTotalAmount());
        result.setSupplyDate(supplyOrder.getSupplyDate());
        result.setStatus(YesNoEnum.no);
        result.setSupplierId(supplyOrder.getSupplierId());
        result.setReviewStatus(ReviewStatusEnum.wait);
        result.setCustomerName(supplier.getSupplierName());
        result.setMerchantId(supplier.getMerchantId());
        result.setMerchantName(supplier.getMerchantName());
        return result;
    }

    /**
     * 查询应付账单 是否通过审核 带商家名称
     * @param supplierPayment 必需 pmId / supplierPaymentId
     * @return 不为确认状态时 返回null
     */
    @Override
    public SupplierPayment checkPayment(SupplierPayment supplierPayment) {
        String pmId = supplierPayment.getPmId();
        String paymentSn = supplierPayment.getSupplierPaymentId();
        QueryWrapper<SupplierPayment> query = new QueryWrapper<>();
        // 通过审核
        query.lambda()
                .eq(SupplierPayment::getPmId, pmId)
                .eq(SupplierPayment::getReviewStatus, ReviewStatusEnum.success)
                .eq(SupplierPayment::getSupplierPaymentId, paymentSn);
        SupplierPayment payment = supplierPaymentService.getOne(query);
        if (null == payment || null == payment.getBillType()) {
            return null;
        }
        return payment;
    }


    /**
     * 批量创建 应付账单  都是 采购应付
     * 根据 备货日期
     *
     * @param supplyOrder pmId/ 备货日期
     * @return
     */
    @Override
    public String createPayableBatch(SupplyOrder supplyOrder) {
        LocalDate supplyDate = supplyOrder.getSupplyDate();

        SupplyOrderReq req  = new SupplyOrderReq();
        req.setSupplyDate(supplyDate);
        List<SupplyOrder> list = scmOpcUtils.querySupplyOrderList(req);
        if (CollUtil.isEmpty(list)) {
            throw new ErrorDataException("所选时间批次找不到订单");
        }
        SupplierPayment supplierPayment = new SupplierPayment();
        supplierPayment.setBillType(BillTypeEnum.purchase);
        // 创建 应付账单
        SupplierPayment create;
        int num = 0;
        for (SupplyOrder order : list) {
            supplierPayment.setPayableSn(order.getSupplySn());
            create = createPayable(supplierPayment);
            if (null != create) {
                num++;
            }
        }
        if (num > 0) {
            return "所选时间批次账单数为" + num;
        }
        return null;
    }

    /**
     * 查询应付账单是否可审核 对应订单需为确认状态
     * @param pmId
     * @param supplierPaymentId
     * @return 账单更新金额
     */
    @Override
    public SupplierPayment checkPayable(String pmId, String supplierPaymentId) {
        SupplierPayment result;
        QueryWrapper<SupplierPayment> query = new QueryWrapper<>();
        query.lambda()
                .eq(SupplierPayment::getPmId, pmId)
                .eq(SupplierPayment::getSupplierPaymentId, supplierPaymentId);
        SupplierPayment payment = supplierPaymentService.getOne(query);
        if(null == payment || null == payment.getBillType()){
            return null;
        }
        // 不同类型处理
        switch (payment.getBillType()) {
            case purchase:
                // 采购应付
                result = checkPayableByBuyOrder(pmId, payment);
                break;
            case orderBack:
                // 订单退货应付
                result = checkPayableByReturnOrder(pmId, payment);
                break;
            default:
                result = null;
        }
        return result;
    }

    /**
     * 订单退货应付 是否为确认状态,及对应金额
     * @param pmId
     * @param payment
     * @return
     */
    private SupplierPayment checkPayableByReturnOrder(String pmId, SupplierPayment payment) {
        // 状态:已退货
        ReturnOrderReq req = new ReturnOrderReq();
        req.setPmId(pmId);
        req.setReturnStatus(ReturnStatusEnum.goods_back);
        req.setReturnSn(payment.getPayableSn());
        ReturnOrder returnOrder = scmOpcUtils.queryReturnOrder(req);
        if (null == returnOrder) {
            return null;
        }
        BigDecimal total = returnOrder.getTotalAmount();
        if(null == total){
            return null;
        }
        // 更新
        SupplierPayment update = new SupplierPayment();
        update.setId(payment.getId());
        update.setSupplierPayment(total);
        supplierPaymentService.updateById(update);
        payment.setSupplierPayment(total);
        return payment;
    }

    /**
     * 采购应付账单 是否为确认状态,及对应金额
     * @param pmId
     * @param payment
     * @return
     */
    private SupplierPayment checkPayableByBuyOrder(String pmId, SupplierPayment payment) {
        // 采购应付 已中标 已收货
//        QueryWrapper<OfferOrder> queryWrapper = new QueryWrapper<>();
//        queryWrapper.lambda()
//                .eq(OfferOrder::getPmId, pmId)
//                .eq(OfferOrder::getStatus, PdsOfferStatusEnum.bidding)
//                .eq(OfferOrder::getShipStatus, ShipStatusEnum.receiveCargo)
//                .eq(OfferOrder::getOfferOrderId, payment.getPayableSn());
        OfferOrderReq offerOrderReq = new OfferOrderReq();
        offerOrderReq.setPmId(pmId);
        offerOrderReq.setStatus(PdsOfferStatusEnum.bidding);
        offerOrderReq.setShipStatus(ShipStatusEnum.receiveCargo);
        offerOrderReq.setOfferOrderId(payment.getPayableSn());
        OfferOrder offerOrder = scmOpcUtils.queryOfferOrder(offerOrderReq);
        if (null == offerOrder) {
            return null;
        }
        BigDecimal total = offerOrder.getTotalAmount();
        if (null == total){
            return null;
        }
        // 更新
        SupplierPayment update = new SupplierPayment();
        update.setId(payment.getId());
        update.setSupplierPayment(total);
        supplierPaymentService.updateById(update);
        payment.setSupplierPayment(total);
        return payment;
    }

    /**
     *  审核应付账单
     * @param supplierPayment 必需 pmId / reviewStatus / supplierPayment/supplierPaymentId 可选: remarks
     * @return
     */
    @Override
    public boolean reviewPayment(SupplierPayment supplierPayment) {
        QueryWrapper<SupplierPayment> query = new QueryWrapper<>();
        query.lambda()
                .eq(SupplierPayment::getPmId, supplierPayment.getPmId())
                .eq(SupplierPayment::getSupplierPaymentId, supplierPayment.getSupplierPaymentId());
        SupplierPayment origin = supplierPaymentService.getOne(query);
        if(null == origin){
            return false;
        }
        supplierPayment.setId(origin.getId());
        // 审核通过时 修改金额
        if(supplierPayment.getReviewStatus() != ReviewStatusEnum.success){
            supplierPayment.setSupplierPayment(null);
        }
        return supplierPaymentService.updateById(supplierPayment);
    }

    /**
     * 分页查询   未使用
     * @param page
     * @param supplierPayment
     * @return
     */
    @Override
    public IPage fetchPage(Page page, SupplierPayment supplierPayment) {
        IPage resp = supplierPaymentService.page(page, Wrappers.query(supplierPayment).orderByDesc("supplier_payment_id"));
        List<SupplierPaymentResp> list = new ArrayList<>();
        SupplierPaymentResp paymentResp;
        if(CollUtil.isNotEmpty(resp.getRecords())){
            for(Object b:resp.getRecords()){
                paymentResp = BeanUtil.toBean(b, SupplierPaymentResp.class);
                if (paymentResp.getBillType() == null) {
                    continue;
                }
                // 客户名称 /商家名称 设置
                String customerName = "";
                String merchantName = "";
                switch (paymentResp.getBillType()) {
                    case purchase:
                        // 采购应付
                        SupplierReq supplierReq = new SupplierReq();
                        supplierReq.setId(paymentResp.getSupplierId());
                        Supplier supplier = scmOpcUtils.querySupplier(supplierReq);
                        if(null != supplier){
                            customerName = supplier.getSupplierName();
                            merchantName = supplier.getMerchantName();
                        }
                        break;
                    case orderBack:
                        // 订单退货应付
                        BuyerReq req = new BuyerReq();
                        req.setId(paymentResp.getSupplierId());
                        Buyer buyer = scmOpcUtils.queryBuyer(req);
                        if(null != buyer){
                            customerName = buyer.getBuyerName();
                            merchantName = buyer.getMerchantName();
                        }
                        break;
                    default:
                }
                paymentResp.setCustomerName(customerName);
                paymentResp.setMerchantName(merchantName);
                // todo 制单人
                list.add(paymentResp);
            }
        }
        resp.setRecords(list);
        return resp;
    }

    /**
     * 查询账单详情 TODO 需修改
     * @param req
     * @return
     */
    @Override
    public List queryPaymentDetail(PaymentDetailReq req) {
//        if(req.getReceivableSn().indexOf("OY") == 0){
//            OfferOrderReq orderReq = new OfferOrderReq();
//            orderReq.setPmId(req.getPmId());
//            orderReq.setOfferOrderId(req.getReceivableSn());
//            List list = scmOpcUtils.queryOfferOrderList(orderReq);
//            if(list.isEmpty()){
//                throw new EmptyDataException();
//            }
//            return list;
//        }
//        if(!scmOpcUtils.fetchReturnOrder(req.getPmId(),req.getReceivableSn())){
//            throw new EmptyDataException();
//        }
        ReturnOrderDetailReq returnOrderDetailReq = new ReturnOrderDetailReq();
        returnOrderDetailReq.setPmId(req.getPmId());
        returnOrderDetailReq.setReturnSn(req.getReceivableSn());
        return scmOpcUtils.queryReturnOrderDetailList(returnOrderDetailReq);
    }

}
